home *** CD-ROM | disk | FTP | other *** search
/ SunSoft Catalyst CDWARE 1996 May to August / Catalyst CDWARE 1996 May to August.iso / .products / .bin / httpd / src / http_config.c < prev    next >
C/C++ Source or Header  |  1995-05-18  |  36KB  |  1,036 lines

  1. /*
  2.  * http_config.c: auxillary functions for reading httpd's config file
  3.  * and converting filenames into a namespace
  4.  *
  5.  * All code contained herein is covered by the Copyright as distributed
  6.  * in the README file in the main directory of the distribution of 
  7.  * NCSA HTTPD.
  8.  *
  9.  * Based on NCSA HTTPd 1.3 by Rob McCool 
  10.  *
  11.  * 10/28/94  cvarela
  12.  *      Added config options AgentLog and RefererLog for extra log info
  13.  *
  14.  * 02/19/95  blong
  15.  *    Added config options MaxServers and StartServers for configuration
  16.  *    defined children
  17.  *
  18.  * 03/21/95 cvarela
  19.  *      Added RefererIgnore to ignore certain URIs when logging referers
  20.  */
  21.  
  22. #include "httpd.h"
  23. #include "new.h"
  24.  
  25. /* Server config globals */
  26. int standalone;
  27. int port;
  28. uid_t user_id;
  29. gid_t group_id;
  30. char server_root[MAX_STRING_LEN];
  31. char error_fname[MAX_STRING_LEN];
  32. char xfer_fname[MAX_STRING_LEN];
  33. char agent_fname[MAX_STRING_LEN];
  34. char referer_fname[MAX_STRING_LEN];
  35. char referer_ignore[MAX_STRING_LEN];
  36. char pid_fname[MAX_STRING_LEN];
  37. char server_admin[MAX_STRING_LEN];
  38. char *server_hostname;
  39. char srm_confname[MAX_STRING_LEN];
  40. char server_confname[MAX_STRING_LEN];
  41. char access_confname[MAX_STRING_LEN];
  42. char types_confname[MAX_STRING_LEN];
  43. char annotation_server[MAX_STRING_LEN];  /* SSG 4/5/95 annotation server url */
  44. int timeout;
  45. int do_rfc931;
  46.  
  47. #ifndef NO_PASS
  48. int max_servers;
  49. int start_servers;
  50. #endif
  51.  
  52.  
  53. void process_server_config(FILE *errors) {
  54.     FILE *cfg;
  55.     char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
  56.     int n=0;
  57.  
  58.     standalone = 1;
  59.     port = DEFAULT_PORT;
  60.     user_id = uname2id(DEFAULT_USER);
  61.     group_id = gname2id(DEFAULT_GROUP);
  62.  
  63. #ifndef NO_PASS
  64.     max_servers = DEFAULT_MAX_DAEMON;
  65.     start_servers = DEFAULT_START_DAEMON;
  66. #endif
  67.  
  68.     /* ServerRoot set in httpd.c */
  69.     make_full_path(server_root,DEFAULT_ERRORLOG,error_fname);
  70.     make_full_path(server_root,DEFAULT_XFERLOG,xfer_fname);
  71.     make_full_path(server_root,DEFAULT_AGENTLOG,agent_fname);
  72.     make_full_path(server_root,DEFAULT_REFERERLOG,referer_fname);
  73.     make_full_path(server_root,DEFAULT_PIDLOG,pid_fname);
  74.     strcpy(referer_ignore,DEFAULT_REFERERIGNORE);
  75.     strcpy(server_admin,DEFAULT_ADMIN);
  76.     server_hostname = NULL;
  77.     make_full_path(server_root,RESOURCE_CONFIG_FILE,srm_confname);
  78.     /* server_confname set in httpd.c */
  79.     make_full_path(server_root,ACCESS_CONFIG_FILE,access_confname);
  80.     make_full_path(server_root,TYPES_CONFIG_FILE,types_confname);
  81.  
  82.     /* initialize the ann.server to nothing */
  83.     annotation_server[0] = '\0';
  84.  
  85.     timeout = DEFAULT_TIMEOUT;
  86.     do_rfc931 = DEFAULT_RFC931;
  87.  
  88.  
  89.     if(!(cfg = fopen(server_confname,"r"))) {
  90.         fprintf(errors,"httpd: could not open server config. file %s\n",server_confname);
  91.         perror("fopen");
  92.         exit(1);
  93.     }
  94.     /* Parse server config file. Remind me to learn yacc. */
  95.     while(!(cfg_getline(l,MAX_STRING_LEN,cfg))) {
  96.         ++n;
  97.         if((l[0] != '#') && (l[0] != '\0')) {
  98.             cfg_getword(w,l);
  99.             if(!strcasecmp(w,"ServerType")) {
  100.                 if(!strcasecmp(l,"inetd")) standalone=0;
  101.                 else if(!strcasecmp(l,"standalone")) standalone=1;
  102.                 else {
  103.                     fprintf(errors,"Syntax error on line %d of %s:\n",n,server_confname);
  104.                     fprintf(errors,"ServerType is either inetd or standalone.\n");
  105.                     exit(1);
  106.                 }
  107.             }
  108.             else if(!strcasecmp(w,"Port")) {
  109.                 cfg_getword(w,l);
  110.                 port = atoi(w);
  111.             }
  112.             else if(!strcasecmp(w,"User")) {
  113.                 cfg_getword(w,l);
  114.                 user_id = uname2id(w);
  115.             } 
  116.             else if(!strcasecmp(w,"Group")) {
  117.                 cfg_getword(w,l);
  118.                 group_id = gname2id(w);
  119.             }
  120.             else if(!strcasecmp(w,"ServerAdmin")) {
  121.                 cfg_getword(w,l);
  122.                 strcpy(server_admin,w);
  123.             }
  124.         /* SSG-4/4/95 read annotation server directive */
  125.         else if(!strcasecmp(w,"Annotation-Server")) {
  126.         cfg_getword(w,l);
  127.         strcpy(annotation_server, w);
  128.         } 
  129.             else if(!strcasecmp(w,"ServerName")) {
  130.                 cfg_getword(w,l);
  131.                 if(server_hostname)
  132.                     free(server_hostname);
  133.                 if(!(server_hostname = strdup(w)))
  134.                     die(NO_MEMORY,"process_resource_config",errors);
  135.             }
  136.             else if(!strcasecmp(w,"ServerRoot")) {
  137.                 cfg_getword(w,l);
  138.                 if(!is_directory(w)) {
  139.                     fprintf(errors,"Syntax error on line %d of %s:\n",n,server_confname);
  140.                     fprintf(errors,"%s is not a valid directory.\n",w);
  141.                     exit(1);
  142.                 }
  143.                 strcpy(server_root,w);
  144.           make_full_path(server_root,DEFAULT_ERRORLOG,error_fname);
  145.           make_full_path(server_root,DEFAULT_XFERLOG,xfer_fname);
  146.           make_full_path(server_root,DEFAULT_AGENTLOG,agent_fname);
  147.           make_full_path(server_root,DEFAULT_REFERERLOG,referer_fname);
  148.           make_full_path(server_root,DEFAULT_PIDLOG,pid_fname);
  149.           make_full_path(server_root,RESOURCE_CONFIG_FILE,srm_confname);
  150.           make_full_path(server_root,ACCESS_CONFIG_FILE,access_confname);
  151.           make_full_path(server_root,TYPES_CONFIG_FILE,types_confname);
  152.             }
  153.             else if(!strcasecmp(w,"ErrorLog")) {
  154.                 cfg_getword(w,l);
  155.                 if(w[0] != '/')
  156.                     make_full_path(server_root,w,error_fname);
  157.                 else 
  158.                     strcpy(error_fname,w);
  159.             } 
  160.             else if(!strcasecmp(w,"TransferLog")) {
  161.                 cfg_getword(w,l);
  162.                 if(w[0] != '/')
  163.                     make_full_path(server_root,w,xfer_fname);
  164.                 else strcpy(xfer_fname,w);
  165.             }
  166.             else if(!strcasecmp(w,"AgentLog")) {
  167.                 cfg_getword(w,l);
  168.                 if(w[0] != '/')
  169.                     make_full_path(server_root,w,agent_fname);
  170.                 else strcpy(agent_fname,w);
  171.             }
  172.             else if(!strcasecmp(w,"RefererLog")) {
  173.                 cfg_getword(w,l);
  174.                 if(w[0] != '/')
  175.                     make_full_path(server_root,w,referer_fname);
  176.                 else strcpy(referer_fname,w);
  177.             }
  178.             else if(!strcasecmp(w,"RefererIgnore")) {
  179.                 cfg_getword(w,l);
  180.                 strcpy(referer_ignore,w);
  181.             }
  182.             else if(!strcasecmp(w,"PidFile")) {
  183.                 cfg_getword(w,l);
  184.                 if(w[0] != '/')
  185.                     make_full_path(server_root,w,pid_fname);
  186.                 else strcpy(pid_fname,w);
  187.             }
  188.             else if(!strcasecmp(w,"AccessConfig")) {
  189.                 cfg_getword(w,l);
  190.                 if(w[0] != '/')
  191.                     make_full_path(server_root,w,access_confname);
  192.                 else strcpy(access_confname,w);
  193.             }
  194.             else if(!strcasecmp(w,"ResourceConfig")) {
  195.                 cfg_getword(w,l);
  196.                 if(w[0] != '/')
  197.                     make_full_path(server_root,w,srm_confname);
  198.                 else strcpy(srm_confname,w);
  199.             }
  200.             else if(!strcasecmp(w,"TypesConfig")) {
  201.                 cfg_getword(w,l);
  202.                 if(w[0] != '/')
  203.                     make_full_path(server_root,w,types_confname);
  204.                 else strcpy(types_confname,w);
  205.             }
  206.             else if(!strcasecmp(w,"Timeout"))
  207.                 timeout = atoi(l);
  208.             else if(!strcasecmp(w,"IdentityCheck")) {
  209.                 cfg_getword(w,l);
  210.                 if(!strcasecmp(w,"on"))
  211.                     do_rfc931 = 1;
  212.                 else if(!strcasecmp(w,"off"))
  213.                     do_rfc931 = 0;
  214.                 else {
  215.                     fprintf(errors,"Syntax error on line %d of %s:\n",n,
  216.                             server_confname);
  217.                     fprintf(errors,"IdentityCheck must be on or off.\n");
  218.                 }
  219.             }
  220.         else if(!strcasecmp(w,"MaxServers")) {
  221. #ifndef NO_PASS
  222.         max_servers = atoi(l);
  223. #else
  224.         fprintf(errors,"This compile doesn't support MaxServers on line %d of %s:\n",n,server_confname);
  225. #endif        
  226.         }
  227.         else if(!strcasecmp(w,"StartServers")) {
  228. #ifndef NO_PASS
  229.         start_servers = atoi(l);
  230. #else
  231.         fprintf(errors,"This compile doesn't support StartServers on line %d of %s:\n",n,server_confname);
  232. #endif
  233.             }
  234.             else {
  235.                 fprintf(errors,"Syntax error on line %d of %s:\n",n,server_confname);
  236.                 fprintf(errors,"Unknown keyword %s.\n",w);
  237.                 exit(1);
  238.             }
  239.         }
  240.     }
  241.     fclose(cfg);
  242. }
  243.  
  244. /* Document config globals */
  245. char user_dir[MAX_STRING_LEN];
  246. char index_name[MAX_STRING_LEN];
  247. char access_name[MAX_STRING_LEN];
  248. char document_root[MAX_STRING_LEN];
  249. char default_type[MAX_STRING_LEN];
  250. char local_default_type[MAX_STRING_LEN];
  251. char default_icon[MAX_STRING_LEN];
  252. char local_default_icon[MAX_STRING_LEN];
  253.  
  254. void process_resource_config(FILE *errors) {
  255.     FILE *cfg;
  256.     char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
  257.     int n=0;
  258.  
  259.     strcpy(user_dir,DEFAULT_USER_DIR);
  260.     strcpy(index_name,DEFAULT_INDEX);
  261.     strcpy(access_name,DEFAULT_ACCESS_FNAME);
  262.     strcpy(document_root,DOCUMENT_LOCATION);
  263.     strcpy(default_type,DEFAULT_TYPE);
  264.     default_icon[0] = '\0';
  265.  
  266.     add_opts_int(0,"/",errors);
  267.  
  268.     if(!(cfg = fopen(srm_confname,"r"))) {
  269.         fprintf(errors,"httpd: could not open document config. file %s\n",
  270.                 srm_confname);
  271.         perror("fopen");
  272.         exit(1);
  273.     }
  274.  
  275.     while(!(cfg_getline(l,MAX_STRING_LEN,cfg))) {
  276.         ++n;
  277.         if((l[0] != '#') && (l[0] != '\0')) {
  278.             cfg_getword(w,l);
  279.             
  280.             if(!strcasecmp(w,"ScriptAlias")) {
  281.                 char w2[MAX_STRING_LEN];
  282.             
  283.                 cfg_getword(w,l);
  284.                 cfg_getword(w2,l);
  285.                 if((w[0] == '\0') || (w2[0] == '\0')) {
  286.                     fprintf(errors,"Syntax error on line %d of %s:\n",n,
  287.                             srm_confname);
  288.                     fprintf(errors,
  289. "ScriptAlias must be followed by a fakename, one space, then a realname.\n");
  290.                     exit(1);
  291.                 }                
  292.                 add_alias(w,w2,SCRIPT_CGI);
  293.             }
  294.             else if(!strcasecmp(w,"OldScriptAlias")) {
  295.                 char w2[MAX_STRING_LEN];
  296.             
  297.                 cfg_getword(w,l);
  298.                 cfg_getword(w2,l);
  299.                 if((w[0] == '\0') || (w2[0] == '\0')) {
  300.                     fprintf(errors,"Syntax error on line %d of %s:\n",n,
  301.                             srm_confname);
  302.                     fprintf(errors,
  303. "ScriptAlias must be followed by a fakename, one space, then a realname.\n");
  304.                     exit(1);
  305.                 }                
  306.                 add_alias(w,w2,SCRIPT_NCSA);
  307.             }
  308.             else if(!strcasecmp(w,"UserDir")) {
  309.                 cfg_getword(w,l);
  310.                 if(!strcmp(w,"DISABLED"))
  311.                     user_dir[0] = '\0';
  312.                 else
  313.                     strcpy(user_dir,w);
  314.             }
  315.             else if(!strcasecmp(w,"DirectoryIndex")) {
  316.                 cfg_getword(w,l);
  317.                 strcpy(index_name,w);
  318.             } 
  319.             else if(!strcasecmp(w,"DefaultType")) {
  320.                 cfg_getword(w,l);
  321.                 strcpy(default_type,w);
  322.             }
  323.             else if(!strcasecmp(w,"AccessFileName")) {
  324.                 cfg_getword(w,l);
  325.                 strcpy(access_name,w);
  326.             } 
  327.             else if(!strcasecmp(w,"DocumentRoot")) {
  328.                 cfg_getword(w,l);
  329.                 if(!is_directory(w)) {
  330.                     fprintf(errors,"Syntax error on line %d of %s:\n",n,
  331.                             srm_confname);
  332.                     fprintf(errors,"%s is not a valid directory.\n",w);
  333.                     exit(1);
  334.                 }
  335.                 strcpy(document_root,w);
  336.             } 
  337.             else if(!strcasecmp(w,"Alias")) {
  338.                 char w2[MAX_STRING_LEN];
  339.         
  340.                 cfg_getword(w,l);
  341.                 cfg_getword(w2,l);
  342.                 if((w[0] == '\0') || (w2[0] == '\0')) {
  343.                     fprintf(errors,"Syntax error on line %d of %s:\n",n,
  344.                             srm_confname);
  345.                     fprintf(errors,
  346. "Alias must be followed by a fakename, one space, then a realname.\n");
  347.                     exit(1);
  348.                 }                
  349.                 add_alias(w,w2,STD_DOCUMENT);
  350.             }
  351.             else if(!strcasecmp(w,"AddType")) {
  352.                 char w2[MAX_STRING_LEN];
  353.                 cfg_getword(w,l);
  354.                 cfg_getword(w2,l);
  355.                 if((w[0] == '\0') || (w2[0] == '\0')) {
  356.                     fprintf(errors,"Syntax error on line %d of %s:\n",n,
  357.                             srm_confname);
  358.                     fprintf(errors,
  359. "AddType must be followed by a type, one space, then a file or extension.\n");
  360.                     exit(1);
  361.                 }
  362.                 add_type(w2,w,errors);
  363.             }
  364.             else if(!strcasecmp(w,"AddEncoding")) {
  365.                 char w2[MAX_STRING_LEN];
  366.                 cfg_getword(w,l);
  367.                 cfg_getword(w2,l);
  368.                 if((w[0] == '\0') || (w2[0] == '\0')) {
  369.                     fprintf(errors,"Syntax error on line %d of %s:\n",n,
  370.                             srm_confname);
  371.                     fprintf(errors,
  372. "AddEncoding must be followed by a type, one space, then a file or extension.\n");
  373.                     exit(1);
  374.                 }
  375.          add_encoding(w2,w,errors);
  376.             }
  377.             else if(!strcasecmp(w,"Redirect")) {
  378.                 char w2[MAX_STRING_LEN];
  379.                 cfg_getword(w,l);
  380.                 cfg_getword(w2,l);
  381.                 if((w[0] == '\0') || (w2[0] == '\0') || (!is_url(w2))) {
  382.                     fprintf(errors,"Syntax error on line %d of %s:\n",n,
  383.                             srm_confname);
  384.                     fprintf(errors,
  385. "Redirect must be followed by a document, one space, then a URL.\n");
  386.                     exit(1);
  387.                 }
  388.                 add_redirect(w,w2);
  389.             }
  390.             else if(!strcasecmp(w,"FancyIndexing")) {
  391.                 cfg_getword(w,l);
  392.                 if(!strcmp(w,"on"))
  393.                     add_opts_int(FANCY_INDEXING,"/",errors);
  394.                 else if(!strcmp(w,"off"))
  395.                     add_opts_int(0,"/",errors);
  396.                 else {
  397.                     fprintf(errors,"Syntax error on line %d of %s:\n",n,
  398.                             srm_confname);
  399.                     fprintf(errors,"FancyIndexing must be on or off.\n");
  400.                     exit(1);
  401.                 }
  402.             }
  403.             else if(!strcasecmp(w,"AddDescription")) {
  404.                 char desc[MAX_STRING_LEN];
  405.                 int fq;
  406.                 if((fq = ind(l,'\"')) == -1) {
  407.                     fprintf(errors,"Syntax error on line %d of %s:\n",n,
  408.                             srm_confname);
  409. fprintf(errors,"AddDescription must have quotes around the description.\n");
  410.                     exit(1);
  411.                 }
  412.                 else {
  413.                     getword(desc,&l[++fq],'\"');
  414.                     cfg_getword(w,&l[fq]);
  415.                     add_desc(BY_PATH,desc,w,"/",errors);
  416.                 }
  417.             }
  418.             else if(!strcasecmp(w,"IndexIgnore")) {
  419.                 while(l[0]) {
  420.                     cfg_getword(w,l);
  421.                     add_ignore(w,"/",errors);
  422.                 }
  423.             }
  424.             else if(!strcasecmp(w,"AddIcon")) {
  425.                 char w2[MAX_STRING_LEN];
  426.                 cfg_getword(w2,l);
  427.                 while(l[0]) {
  428.                     cfg_getword(w,l);
  429.                     add_icon(BY_PATH,w2,w,"/",errors);
  430.                 }
  431.             }
  432.             else if(!strcasecmp(w,"AddIconByType")) {
  433.                 char w2[MAX_STRING_LEN];
  434.                 cfg_getword(w2,l);
  435.                 while(l[0]) {
  436.                     cfg_getword(w,l);
  437.                     add_icon(BY_TYPE,w2,w,"/",errors);
  438.                 }
  439.             }
  440.             else if(!strcasecmp(w,"AddIconByEncoding")) {
  441.                 char w2[MAX_STRING_LEN];
  442.                 cfg_getword(w2,l);
  443.                 while(l[0]) {
  444.                     cfg_getword(w,l);
  445.                     add_icon(BY_ENCODING,w2,w,"/",errors);
  446.                 }
  447.             }
  448.             else if(!strcasecmp(w,"AddAlt")) {
  449.                 char w2[MAX_STRING_LEN];
  450.                 cfg_getword(w2,l);
  451.                 while(l[0]) {
  452.                     cfg_getword(w,l);
  453.                     add_alt(BY_PATH,w2,w,"/",errors);
  454.                 }
  455.             }
  456.             else if(!strcasecmp(w,"AddAltByType")) {
  457.                 char w2[MAX_STRING_LEN];
  458.                 cfg_getword(w2,l);
  459.                 while(l[0]) {
  460.                     cfg_getword(w,l);
  461.                     add_alt(BY_TYPE,w2,w,"/",errors);
  462.                 }
  463.             }
  464.             else if(!strcasecmp(w,"AddAltByEncoding")) {
  465.                 char w2[MAX_STRING_LEN];
  466.                 cfg_getword(w2,l);
  467.                 while(l[0]) {
  468.                     cfg_getword(w,l);
  469.                     add_alt(BY_ENCODING,w2,w,"/",errors);
  470.                 }
  471.             }
  472.             else if(!strcasecmp(w,"DefaultIcon")) {
  473.                 cfg_getword(w,l);
  474.                 strcpy(default_icon,w);
  475.             }
  476.             else if(!strcasecmp(w,"ReadmeName")) {
  477.                 cfg_getword(w,l);
  478.                 add_readme(w,"/",errors);
  479.             }
  480.             else if(!strcasecmp(w,"HeaderName")) {
  481.                 cfg_getword(w,l);
  482.                 add_header(w,"/",errors);
  483.             }
  484.             else if(!strcasecmp(w,"IndexOptions"))
  485.                 add_opts(l,"/",errors);
  486.         else if (!strcasecmp(w,"ErrorDocument")) {
  487.         char w2[MAX_STRING_LEN];
  488.             cfg_getword(w,l); /* Get errornum */
  489.         cfg_getword(w2,l); /* Get filename */
  490.         add_error(w,w2);
  491.             }
  492.             else {
  493.                 fprintf(errors,"Syntax error on line %d of %s:\n",n,
  494.                         srm_confname);
  495.                 fprintf(errors,"Unknown keyword %s.\n",w);
  496.                 exit(1);
  497.             }
  498.         }
  499.     }
  500.     fclose(cfg);
  501.  
  502.     Saved_Forced = forced_types;
  503.     Saved_Encoding = encoding_types;
  504.     /* Save the number of global aliases */
  505.     save_aliases();
  506. }
  507.  
  508.  
  509. /* Auth Globals */
  510. char *auth_type;
  511. char *auth_name;
  512. char *auth_pwfile;
  513. char *auth_grpfile;
  514.  
  515. /* Access Globals*/
  516. int num_sec;
  517. /* number of security directories in access config file */
  518. int num_sec_config;
  519. security_data sec[MAX_SECURITY];
  520.  
  521. void access_syntax_error(int n, char *err, char *file, FILE *out) {
  522.     if(!file) {
  523.         fprintf(out,"Syntax error on line %d of access config. file.\n",n);
  524.         fprintf(out,"%s\n",err);
  525.         exit(1);
  526.     }
  527.     else {
  528.         char e[MAX_STRING_LEN];
  529.         sprintf(e,"httpd: syntax error or override violation in access control file %s, reason: %s",file,err);
  530.         die(SERVER_ERROR,e,out);
  531.     }
  532. }
  533.  
  534. int parse_access_dir(FILE *f, int line, char or, char *dir, 
  535.                      char *file, FILE *out) 
  536. {
  537.     char l[MAX_STRING_LEN];
  538.     char w[MAX_STRING_LEN];
  539.     char w2[MAX_STRING_LEN];
  540.     int n=line;
  541.     register int x,i;
  542.  
  543.     x = num_sec;
  544.  
  545.     sec[x].opts=OPT_UNSET;
  546.     sec[x].override = or;
  547.     if(!(sec[x].d = (char *)malloc((sizeof(char)) * (strlen(dir) + 2))))
  548.         die(NO_MEMORY,"parse_access_dir",out);
  549.     if(is_matchexp(dir))
  550.         strcpy(sec[x].d,dir);
  551.     else
  552.         strcpy_dir(sec[x].d,dir);
  553.  
  554.     sec[x].auth_type = NULL;
  555.     sec[x].auth_name = NULL;
  556.     sec[x].auth_pwfile = NULL;
  557.     sec[x].auth_grpfile = NULL;
  558.     for(i=0;i<METHODS;i++) {
  559.         sec[x].order[i] = DENY_THEN_ALLOW;
  560.         sec[x].num_allow[i]=0;
  561.         sec[x].num_deny[i]=0;
  562.         sec[x].num_auth[i] = 0;
  563.     }
  564.  
  565.     while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
  566.         ++n;
  567.         if((l[0] == '#') || (!l[0])) continue;
  568.         cfg_getword(w,l);
  569.  
  570.         if(!strcasecmp(w,"AllowOverride")) {
  571.             if(file)
  572.                 access_syntax_error(n,"override violation",file,out);
  573.             sec[x].override = OR_NONE;
  574.             while(l[0]) {
  575.                 cfg_getword(w,l);
  576.                 if(!strcasecmp(w,"Limit"))
  577.                     sec[x].override |= OR_LIMIT;
  578.                 else if(!strcasecmp(w,"Options"))
  579.                     sec[x].override |= OR_OPTIONS;
  580.                 else if(!strcasecmp(w,"FileInfo"))
  581.                     sec[x].override |= OR_FILEINFO;
  582.                 else if(!strcasecmp(w,"AuthConfig"))
  583.                     sec[x].override |= OR_AUTHCFG;
  584.                 else if(!strcasecmp(w,"Indexes"))
  585.                     sec[x].override |= OR_INDEXES;
  586.                 else if(!strcasecmp(w,"None"))
  587.                     sec[x].override = OR_NONE;
  588.                 else if(!strcasecmp(w,"All")) 
  589.                     sec[x].override = OR_ALL;
  590.                 else {
  591.                     access_syntax_error(n,
  592. "Unknown keyword in AllowOverride directive.",file,out);
  593.                 }
  594.             }
  595.         } 
  596.         else if(!strcasecmp(w,"Options")) {
  597.             if(!(or & OR_OPTIONS))
  598.                 access_syntax_error(n,"override violation",file,out);
  599.             sec[x].opts = OPT_NONE;
  600.             while(l[0]) {
  601.                 cfg_getword(w,l);
  602.                 if(!strcasecmp(w,"Indexes"))
  603.                     sec[x].opts |= OPT_INDEXES;
  604.                 else if(!strcasecmp(w,"Includes"))
  605.                     sec[x].opts |= OPT_INCLUDES;
  606.                 else if(!strcasecmp(w,"IncludesNOEXEC"))
  607.                     sec[x].opts |= (OPT_INCLUDES | OPT_INCNOEXEC);
  608.                 else if(!strcasecmp(w,"FollowSymLinks"))
  609.                     sec[x].opts |= OPT_SYM_LINKS;
  610.                 else if(!strcasecmp(w,"SymLinksIfOwnerMatch"))
  611.                     sec[x].opts |= OPT_SYM_OWNER;
  612.                 else if(!strcasecmp(w,"execCGI"))
  613.                     sec[x].opts |= OPT_EXECCGI;
  614.                 else if(!strcasecmp(w,"None")) 
  615.                     sec[x].opts = OPT_NONE;
  616.                 else if(!strcasecmp(w,"All")) 
  617.                     sec[x].opts = OPT_ALL;
  618.                 else {
  619.                     access_syntax_error(n,
  620. "Unknown keyword in Options directive.",file,out);
  621.                 }
  622.             }
  623.         }
  624.         else if(!strcasecmp(w,"AuthName")) {
  625.             if(!(or & OR_AUTHCFG))
  626.                 access_syntax_error(n,"override violation",file,out);
  627.             if(sec[x].auth_name) 
  628.                 free(sec[x].auth_name);
  629.             if(!(sec[x].auth_name = strdup(l)))
  630.                 die(NO_MEMORY,"parse_access_dir",out);
  631.         }
  632.         else if(!strcasecmp(w,"AuthType")) {
  633.             if(!(or & OR_AUTHCFG))
  634.                 access_syntax_error(n,"override violation",file,out);
  635.             cfg_getword(w,l);
  636.             if(sec[x].auth_type) 
  637.                 free(sec[x].auth_type);
  638.             if(!(sec[x].auth_type = strdup(w)))
  639.                 die(NO_MEMORY,"parse_access_dir",out);
  640.         }
  641.         else if(!strcasecmp(w,"AuthUserFile")) {
  642.             if(!(or & OR_AUTHCFG))
  643.                 access_syntax_error(n,"override violation",file,out);
  644.             cfg_getword(w,l);
  645.             if(sec[x].auth_pwfile) 
  646.                 free(sec[x].auth_pwfile);
  647.             if(!(sec[x].auth_pwfile = strdup(w)))
  648.                 die(NO_MEMORY,"parse_access_dir",out);
  649.         }
  650.         else if(!strcasecmp(w,"AuthGroupFile")) {
  651.             if(!(or & OR_AUTHCFG))
  652.                 access_syntax_error(n,"override violation",file,out);
  653.             cfg_getword(w,l);
  654.             if(sec[x].auth_grpfile) 
  655.                 free(sec[x].auth_grpfile);
  656.             if(!(sec[x].auth_grpfile = strdup(w)))
  657.                 die(NO_MEMORY,"parse_access_dir",out);
  658.         }
  659.         else if(!strcasecmp(w,"AddType")) {
  660.             if(!(or & OR_FILEINFO))
  661.                 access_syntax_error(n,"override violation",file,out);
  662.             cfg_getword(w,l);
  663.             cfg_getword(w2,l);
  664.             if((w[0] == '\0') || (w2[0] == '\0')) {
  665.                 access_syntax_error(n,
  666. "AddType must be followed by a type, one space, then a file or extension.",
  667.                                     file,out);
  668.             }
  669.             add_type(w2,w,out);
  670.         }
  671.         else if(!strcasecmp(w,"DefaultType")) {
  672.             if(!(or & OR_FILEINFO))
  673.                 access_syntax_error(n,"override violation",file,out);
  674.             cfg_getword(w,l);
  675.             strcpy(local_default_type,w);
  676.         }
  677.         else if(!strcasecmp(w,"AddEncoding")) {
  678.             if(!(or & OR_FILEINFO))
  679.                 access_syntax_error(n,"override violation",file,out);
  680.             cfg_getword(w,l);
  681.             cfg_getword(w2,l);
  682.             if((w[0] == '\0') || (w2[0] == '\0')) {
  683.                 access_syntax_error(n,
  684. "AddEncoding must be followed by a type, one space, then a file or extension.",
  685.                                     file,out);
  686.             }
  687.             add_encoding(w2,w,out);
  688.         }
  689.         else if(!strcasecmp(w,"DefaultIcon")) {
  690.             if(!(or & OR_INDEXES))
  691.                 access_syntax_error(n,"override violation",file,out);
  692.             cfg_getword(w,l);
  693.             strcpy(local_default_icon,w);
  694.         }
  695.         else if(!strcasecmp(w,"AddDescription")) {
  696.             char desc[MAX_STRING_LEN];
  697.             int fq;
  698.             
  699.             if(!(or & OR_INDEXES))
  700.                 access_syntax_error(n,"override violation",file,out);
  701.             if((fq = ind(l,'\"')) == -1)
  702.                 access_syntax_error(n,"AddDescription must have quotes",
  703.                                     file,out);
  704.             else {
  705.                 getword(desc,&l[++fq],'\"');
  706.                 cfg_getword(w,&l[fq]);
  707.                 add_desc(BY_PATH,desc,w,sec[x].d,out);
  708.             }
  709.         }
  710.         else if(!strcasecmp(w,"IndexIgnore")) {
  711.             if(!(or & OR_INDEXES))
  712.                 access_syntax_error(n,"override violation",file,out);
  713.             while(l[0]) {
  714.                 cfg_getword(w,l);
  715.                 add_ignore(w,sec[x].d,out);
  716.             }
  717.         }
  718.         else if(!strcasecmp(w,"AddIcon")) {
  719.             char w2[MAX_STRING_LEN];
  720.             
  721.             if(!(or & OR_INDEXES))
  722.                 access_syntax_error(n,"override violation",file,out);
  723.             cfg_getword(w2,l);
  724.             while(l[0]) {
  725.                 cfg_getword(w,l);
  726.                 add_icon(BY_PATH,w2,w,sec[x].d,out);
  727.             }
  728.         }
  729.         else if(!strcasecmp(w,"AddIconByType")) {
  730.             char w2[MAX_STRING_LEN];
  731.             
  732.             if(!(or & OR_INDEXES))
  733.                 access_syntax_error(n,"override violation",file,out);
  734.             cfg_getword(w2,l);
  735.             while(l[0]) {
  736.                 cfg_getword(w,l);
  737.                 add_icon(BY_TYPE,w2,w,sec[x].d,out);
  738.             }
  739.         }
  740.         else if(!strcasecmp(w,"AddIconByEncoding")) {
  741.             char w2[MAX_STRING_LEN];
  742.             
  743.             if(!(or & OR_INDEXES))
  744.                 access_syntax_error(n,"override violation",file,out);
  745.             cfg_getword(w2,l);
  746.             while(l[0]) {
  747.                 cfg_getword(w,l);
  748.                 add_icon(BY_ENCODING,w2,w,sec[x].d,out);
  749.             }
  750.         }
  751.         else if(!strcasecmp(w,"ReadmeName")) {
  752.             if(!(or & OR_INDEXES))
  753.                 access_syntax_error(n,"override violation",file,out);
  754.             cfg_getword(w,l);
  755.             add_readme(w,sec[x].d,out);
  756.         }
  757.         else if(!strcasecmp(w,"HeaderName")) {
  758.             if(!(or & OR_INDEXES))
  759.                 access_syntax_error(n,"override violation",file,out);
  760.             cfg_getword(w,l);
  761.             add_header(w,sec[x].d,out);
  762.         }
  763.         else if(!strcasecmp(w,"IndexOptions")) {
  764.             if(!(or & OR_INDEXES))
  765.                 access_syntax_error(n,"override violation",file,out);
  766.             add_opts(l,sec[x].d,out);
  767.         }
  768.         else if(!strcasecmp(w,"Redirect")) {
  769.             if(!(or & OR_FILEINFO))
  770.                 access_syntax_error(n,"override violation",file,out);
  771.             cfg_getword(w,l);
  772.             cfg_getword(w2,l);
  773.             if((w[0] == '\0') || (w2[0] == '\0') || (!is_url(w2))) {
  774.                 access_syntax_error(n,
  775. "Redirect must be followed by a document, one space, then a URL.",file,out);
  776.             }
  777.             if(!file) 
  778.                 add_redirect(w,w2);
  779.             else
  780.                 access_syntax_error(n,
  781. "Redirect no longer supported from .htaccess files.",file,out); 
  782.         }
  783.         else if(!strcasecmp(w,"<Limit")) {
  784.             int m[METHODS];
  785.  
  786.             if(!(or & OR_LIMIT))
  787.                 access_syntax_error(n,"override violation",file,out);
  788.             for(i=0;i<METHODS;i++) m[i] = 0;
  789.             getword(w2,l,'>');
  790.             while(w2[0]) {
  791.                 cfg_getword(w,w2);
  792.                 if(!strcasecmp(w,"GET")) m[M_GET]=1;
  793.                 else if(!strcasecmp(w,"PUT")) m[M_PUT]=1;
  794.                 else if(!strcasecmp(w,"POST")) m[M_POST]=1;
  795.                 else if(!strcasecmp(w,"DELETE")) m[M_DELETE]=1;
  796.             }
  797.             while(1) {
  798.                 if(cfg_getline(l,MAX_STRING_LEN,f))
  799.                     access_syntax_error(n,"Limit missing /Limit",file,out);
  800.                 n++;
  801.                 if((l[0] == '#') || (!l[0])) continue;
  802.  
  803.                 if(!strcasecmp(l,"</Limit>"))
  804.                     break;
  805.                 cfg_getword(w,l);
  806.                 if(!strcasecmp(w,"order")) {
  807.                     if(!strcasecmp(l,"allow,deny")) {
  808.                         for(i=0;i<METHODS;i++)
  809.                             if(m[i])
  810.                                 sec[x].order[i] = ALLOW_THEN_DENY;
  811.                     }
  812.                     else if(!strcasecmp(l,"deny,allow")) {
  813.                         for(i=0;i<METHODS;i++)
  814.                             if(m[i]) 
  815.                                 sec[x].order[i] = DENY_THEN_ALLOW;
  816.                     }
  817.                     else if(!strcasecmp(l,"mutual-failure")) {
  818.                         for(i=0;i<METHODS;i++)
  819.                             if(m[i]) 
  820.                                 sec[x].order[i] = MUTUAL_FAILURE;
  821.                     }
  822.                     else
  823.                         access_syntax_error(n,"Unknown order.",file,out);
  824.                 } 
  825.                 else if((!strcasecmp(w,"allow"))) {
  826.                     cfg_getword(w,l);
  827.                     if(strcmp(w,"from"))
  828.                         access_syntax_error(n,
  829.                                             "allow must be followed by from.",
  830.                                             file,out);
  831.                     while(1) {
  832.                         cfg_getword(w,l);
  833.                         if(!w[0]) break;
  834.                         for(i=0;i<METHODS;i++)
  835.                             if(m[i]) {
  836.                                 int q=sec[x].num_allow[i]++;
  837.                                 if(!(sec[x].allow[i][q] = strdup(w)))
  838.                                     die(NO_MEMORY,"parse_access_dir",out);
  839.                             }
  840.                     }
  841.                 }
  842.                 else if(!strcasecmp(w,"require")) {
  843.                     for(i=0;i<METHODS;i++)
  844.                         if(m[i]) {
  845.                             int q=sec[x].num_auth[i]++;
  846.                             if(!(sec[x].auth[i][q] = strdup(l)))
  847.                                 die(NO_MEMORY,"parse_access_dir",out);
  848.                         }
  849.                 }
  850.                 else if((!strcasecmp(w,"deny"))) {
  851.                     cfg_getword(w,l);
  852.                     if(strcmp(w,"from"))
  853.                         access_syntax_error(n,
  854.                                             "deny must be followed by from.",
  855.                                             file,out);
  856.                     while(1) {
  857.                         cfg_getword(w,l);
  858.                         if(!w[0]) break;
  859.                         for(i=0;i<METHODS;i++)
  860.                             if(m[i]) {
  861.                                 int q=sec[x].num_deny[i]++;
  862.                                 if(!(sec[x].deny[i][q] = strdup(w)))
  863.                                     die(NO_MEMORY,"parse_access_dir",out);
  864.                             }
  865.                     }
  866.                 }
  867.                 else
  868.                     access_syntax_error(n,"Unknown keyword in Limit region.",
  869.                                         file,out);
  870.             }
  871.         }
  872.         else if(!strcasecmp(w,"</Directory>"))
  873.             break;
  874.         else {
  875.             char errstr[MAX_STRING_LEN];
  876.             sprintf(errstr,"Unknown method %s",w);
  877.             access_syntax_error(n,errstr,file,out);
  878.             return -1;
  879.         }
  880.     }
  881.     ++num_sec;
  882.     return n;
  883. }
  884.  
  885.  
  886. void parse_htaccess(char *path, char override, FILE *out) {
  887.     FILE *f;
  888.     char t[MAX_STRING_LEN];
  889.     char d[MAX_STRING_LEN];
  890.  
  891.     strcpy(d,path);
  892.     make_full_path(d,access_name,t);
  893.  
  894.     if((f=fopen(t,"r"))) {
  895.         parse_access_dir(f,-1,override,d,t,out);
  896.         fclose(f);
  897.     }
  898. }
  899.  
  900.  
  901. void process_access_config(FILE *errors) {
  902.     FILE *f;
  903.     char l[MAX_STRING_LEN];
  904.     char w[MAX_STRING_LEN];
  905.     int n;
  906.  
  907.     num_sec = 0; 
  908.     n=0;
  909.     if(!(f=fopen(access_confname,"r"))) {
  910.         fprintf(errors,"httpd: could not open access configuration file %s.\n",
  911.                 access_confname);
  912.         perror("fopen");
  913.         exit(1);
  914.     }
  915.     while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
  916.         ++n;
  917.         if((l[0] == '#') || (!l[0])) continue;
  918.     cfg_getword(w,l);
  919.     if(strcasecmp(w,"<Directory")) {
  920.         fprintf(errors,
  921.             "Syntax error on line %d of access config. file.\n",n);
  922.         fprintf(errors,"Unknown directive %s.\n",w);
  923.         exit(1);
  924.     }
  925.     getword(w,l,'>');
  926.     n=parse_access_dir(f,n,OR_ALL,w,NULL,errors);
  927.     }
  928.     fclose(f);
  929.     num_sec_config = num_sec;
  930. }
  931.  
  932. int get_pw(char *user, char *pw, FILE *errors) {
  933.     FILE *f;
  934.     char errstr[MAX_STRING_LEN];
  935.     char l[MAX_STRING_LEN];
  936.     char w[MAX_STRING_LEN];
  937.  
  938.     if(!(f=fopen(auth_pwfile,"r"))) {
  939.         sprintf(errstr,"Could not open user file %s",auth_pwfile);
  940.         die(SERVER_ERROR,errstr,errors);
  941.     }
  942.     while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
  943.         if((l[0] == '#') || (!l[0])) continue;
  944.         getword(w,l,':');
  945.  
  946.         if(!strcmp(user,w)) {
  947.             strcpy(pw,l);
  948.             fclose(f);
  949.             return 1;
  950.         }
  951.     }
  952.     fclose(f);
  953.     return 0;
  954. }
  955.  
  956.  
  957. struct ge {
  958.     char *name;
  959.     char *members;
  960.     struct ge *next;
  961. };
  962.  
  963. static struct ge *grps;
  964.  
  965. int init_group(char *grpfile, FILE *out) {
  966.     FILE *f;
  967.     struct ge *p;
  968.     char l[HUGE_STRING_LEN],w[HUGE_STRING_LEN];
  969.  
  970.     if(!(f=fopen(grpfile,"r")))
  971.         return 0;
  972.  
  973.     grps = NULL;
  974.     while(!(cfg_getline(l,HUGE_STRING_LEN,f))) {
  975.         if((l[0] == '#') || (!l[0])) continue;
  976.         getword(w,l,':');
  977.         if(!(p = (struct ge *) malloc (sizeof(struct ge)))) {
  978.         fclose(f);
  979.             die(NO_MEMORY,"init_group",out);
  980.     }
  981.         if(!(p->name = strdup(w))) {
  982.         fclose(f);
  983.             die(NO_MEMORY,"init_group",out);
  984.     }
  985.         if(!(p->members = strdup(l))) {
  986.         fclose(f);
  987.             die(NO_MEMORY,"init_group",out);
  988.     }
  989.         p->next = grps;
  990.         grps = p;
  991.     }
  992.     fclose(f);
  993.     return 1;
  994. }
  995.  
  996. /* make global for now. This function is called a lot SSG 4/25/95 */
  997. char mems[HUGE_STRING_LEN],wrdbuf[HUGE_STRING_LEN];
  998. int in_group(char *user, char *group) {
  999.     struct ge *p = grps;
  1000.  
  1001.     while(p) {
  1002.         if(!strcmp(p->name,group)) {
  1003.             strcpy(mems,p->members);
  1004.             while(mems[0]) {
  1005.                 getword(wrdbuf,mems,' ');
  1006.                 if(!strcmp(wrdbuf,user)) 
  1007.                     return 1;
  1008.             }
  1009.         }
  1010.         p=p->next;
  1011.     }
  1012.     return 0;
  1013. }
  1014.  
  1015. void kill_group() {
  1016.     struct ge *p = grps, *q;
  1017.  
  1018.     while(p) {
  1019.         free(p->name);
  1020.         free(p->members);
  1021.         q=p;
  1022.         p=p->next;
  1023.         free(q);
  1024.     }   
  1025. }
  1026.  
  1027. void read_config(FILE *errors)
  1028. {
  1029.     reset_aliases();
  1030.     process_server_config(errors);
  1031.     init_mime();
  1032.     init_indexing();
  1033.     process_resource_config(errors);
  1034.     process_access_config(errors);
  1035. }
  1036.